import pylab;
import scipy.interpolate;
from EdgeArrowShape import EdgeArrowShape;
from PyQt4 import QtCore, QtGui;

class EdgeView(object):
    class InfoStyle(): 
        onlyT, noneInfo = range(2);        
    class Status():
        normal, current = range(2);
        
    def __init__(self, objEdge):
        self.edgePathCache, self.bShowCtrlPts = [], False;
        self.canvasView, self.edgePathShape = None, [];
        self.qTransVal = None;
        self.nTrans = 1;
        self.edgeModel = objEdge.edgeModel;
        self.objEdge = objEdge;
        self.setPenThick(self.nTrans);
        self.createEdgeView();
        self.lineType = 2;
        self.bMaxEdge = False;
        
    def refreshTxts(self):
        if self.nTrans != self.edgeModel.trans:
            self.nTrans = self.edgeModel.trans;
            self.qTransVal.setPlainText(self.edgeModel.txtTrans);
            self.setToolTip(self.edgeModel.txtTrans);
            self.setPenThick(self.nTrans);
            self.updateEdgePathItem();
           
    def createEdgeView(self):
        self.edgePathItem = QtGui.QGraphicsPathItem(self.objEdge);
        self.arrowHead = EdgeArrowShape(self.objEdge, self.objEdge.pointTo);
        self.setSelectable(True);
        self.setToolTip(self.edgeModel.txtTrans);
        self.createTxtTrans();
        
    def setPenThick(self, penThick):
        self.nPenThick = penThick;
        
    def createTxtTrans(self):        
        self.qTransVal = QtGui.QGraphicsTextItem(self.objEdge);
        self.qTransVal.setPlainText(self.edgeModel.txtTrans);
        self.tTrans = self.edgeModel.txtTrans;
    
    def getBoundingRect(self):
        if self.objEdge.scene() == None:
            return self.qRect;
        cView = self.objEdge.scene().canvasView;
        qRect = self.edgePath.boundingRect();
        qRect.setX(qRect.x()-50);
        qRect.setY(qRect.y()-50);
        qRect.setWidth(qRect.width()+100);
        qRect.setHeight(qRect.height()+100); 
        #Restrict BoundingRect to stay always inside the Viewport    
        vP1 = cView.mapToScene(0,0);
        vP2 = cView.mapToScene(cView.rect().width(),cView.rect().height());
        if qRect.x() >= vP2.x()-5:
            qRect.setX(vP2.x()-5);
        if qRect.y() >= vP2.y()-5:
            qRect.setY(vP2.y()-5);
        if qRect.x()+qRect.width() <= vP1.x()+5:
            qRect.setWidth(vP1.x()+5 - qRect.x());
        if qRect.y()+qRect.height() <= vP1.y()+5:
            qRect.setHeight(vP1.y()+5 - qRect.y());
        self.qRect = qRect;
        return qRect;
    
    def updateEdge(self):
        ePath = self.getSpline(); #Update Spline based on the new CtrlPts
        nTo = self.objEdge.nTo;
        self.arrowHead.updateArrow(self.objEdge.gCtrlPt[nTo].pos(), ePath);
        self.qTransVal.setPos(ePath.pointAtPercent(0.2));
    
    def getEdgeRegion(self):
        if self.edgePathCache!=self.edgePath:
            self.edgePathCache = self.edgePath;
            self.edgePathShape = self.getSpline(True);
        return self.edgePathShape;
        
    def getSpline(self, bShape=False):
        self.edgePath = QtGui.QPainterPath();
        self.pathPolygon = QtGui.QPolygonF();
        x, y = [], [];
#         x = [self.objEdge.gCtrlPt[0].pos().x()];
#         if self.objEdge.objFrom.angle == 0:
#             y = [self.objEdge.gCtrlPt[0].pos().y()+1];
#         else:
#             y = [self.objEdge.gCtrlPt[0].pos().y()-1];
#         x = [self.objEdge.gCtrlPt[0].pos().x()];
#         y = [self.objEdge.gCtrlPt[0].pos().y()];
        for i in range(len(self.objEdge.gCtrlPt)):
            x.append(self.objEdge.gCtrlPt[i].pos().x());
            y.append(self.objEdge.gCtrlPt[i].pos().y());
#         print x, y;
        try:
            nT = self.lineType;
#             print nT, len(x), len(y);
            aPos = [x[1:], y[1:]] if x[0]==x[1] and y[0]==y[1] else [x,y];
            nT = nT if len(aPos[0])>nT else len(aPos[0])-1;
#             print aPos, nT, len(aPos[0]), len(aPos[1]);
            tck,u = scipy.interpolate.splprep(aPos,k=nT); #@UnusedVariable                
        except:
            print "except", nT, len(aPos[0]);
            return self.edgePath;
        else:
#             print "else";
            unew = pylab.linspace(0,1,25);
            out = scipy.interpolate.splev(unew,tck);
            for i in range(len(out[0])):
                self.pathPolygon.append(QtCore.QPointF(out[0][i], out[1][i]));
            if bShape:
                for i in range(len(out[0])-1,-1,-1):
                    self.pathPolygon.append(QtCore.QPointF(out[0][i], out[1][i]));
            self.edgePath.addPolygon(self.pathPolygon);            
            self.edgePathItem.setPath(self.edgePath);
            self.updateEdgePathItem();
            return self.edgePath;

    def updateEdgePathItem(self):
        if self.objEdge.isSelected():
            self.qTransVal.setDefaultTextColor(QtCore.Qt.blue);
            self.edgePathItem.setPen(QtGui.QPen(QtGui.QColor(0,0,255, 255), 4));
        elif not self.objEdge.isSelected() and not self.bMaxEdge:
            t = self.nPenThick;
            pThick = 2 + 2.3*self.nPenThick;
            self.edgePathItem.setPen(QtGui.QPen(QtGui.QColor(0,0,0, t*180), pThick));
            self.qTransVal.setDefaultTextColor(QtGui.QColor(0,0,0, t*180+50));
            self.qTransVal.setFont(QtGui.QFont("Arial", 8, t*87+25));
        elif not self.objEdge.isSelected() and self.bMaxEdge:
            self.qTransVal.setDefaultTextColor(QtGui.QColor(0,180,0, 255));
            self.edgePathItem.setPen(QtGui.QPen(QtGui.QColor(0,180,0, 255), 4));
            
    def setMaxEdge(self, bMax):
        self.bMaxEdge = bMax;            
            
    def setSelectable(self, bSelectable):
        self.objEdge.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, bSelectable);
        
    def setToolTip(self, txtTooltip):
        self.objEdge.setToolTip(txtTooltip);
    
    def setZValue(self, zVal):
        self.objEdge.setZValue(zVal);
        
    def showCtrlPts(self, bShow=False):
        for ctrlPt in self.objEdge.gCtrlPt:
            ctrlPt.setVisible(bShow);
            self.bShowCtrlPts = bShow;
            
    def setStyleInfo(self, nStyleInfo):
        infoStyle = EdgeView.InfoStyle;
        if nStyleInfo == infoStyle.onlyT:
            self.setStyle_OnlyT();
        elif nStyleInfo == infoStyle.noneInfo:
            self.setStyle_NoneInfo();
        
    def setStyle_OnlyT(self):
        self.qTransVal.setVisible(True);
        
    def setStyle_NoneInfo(self):
        self.qTransVal.setVisible(False);
        
    def setLineType(self, nType):
        self.lineType = nType;
        self.objEdge.bRefresh = True;

